//: net/mindview/atunit/AtUnitRemover.java
// Displays @Unit annotations in compiled class files. If
// first argument is "-r", @Unit annotations are removed.
// {Args: ..}
// {Requires: javassist.bytecode.ClassFile;
// You must install the Javassist library from
// http://sourceforge.net/projects/jboss/ }
package net.mindview.atunit;

import javassist.*;
import javassist.bytecode.*;
import javassist.bytecode.annotation.*;

import java.io.*;

import net.mindview.util.*;

import static net.mindview.util.Print.*;

public class AtUnitRemover
        implements ProcessFiles.Strategy {
    private static boolean remove = false;

    public static void main(String[] args) throws Exception {
        if (args.length > 0 && args[0].equals("-r")) {
            remove = true;
            String[] nargs = new String[args.length - 1];
            System.arraycopy(args, 1, nargs, 0, nargs.length);
            args = nargs;
        }
        new ProcessFiles(
                new AtUnitRemover(), "class").start(args);
    }

    public void process(File cFile) {
        boolean modified = false;
        try {
            String cName = ClassNameFinder.thisClass(
                    BinaryFile.read(cFile));
            if (!cName.contains("."))
                return; // Ignore unpackaged classes
            ClassPool cPool = ClassPool.getDefault();
            CtClass ctClass = cPool.get(cName);
            for (CtMethod method : ctClass.getDeclaredMethods()) {
                MethodInfo mi = method.getMethodInfo();
                AnnotationsAttribute attr = (AnnotationsAttribute)
                        mi.getAttribute(AnnotationsAttribute.visibleTag);
                if (attr == null) continue;
                for (Annotation ann : attr.getAnnotations()) {
                    if (ann.getTypeName()
                            .startsWith("net.mindview.atunit")) {
                        print(ctClass.getName() + " Method: "
                                + mi.getName() + " " + ann);
                        if (remove) {
                            ctClass.removeMethod(method);
                            modified = true;
                        }
                    }
                }
            }
            // Fields are not removed in this version (see text).
            if (modified)
                ctClass.toBytecode(new DataOutputStream(
                        new FileOutputStream(cFile)));
            ctClass.detach();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
} ///:~
